/*
============================================================================
Name        : assembler.c
Author      : 
Version     :
Copyright   : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
#include <stdio.h> /* standard input/output library */
#include <stdlib.h> /* Standard C Library */
#include <string.h> /* String operations library */
#include <ctype.h> /* Library for useful character operations */
#include <limits.h> /* Library for definitions of common variable type characteristics */

#define MAX_LINE_LENGTH 255
enum{
  DONE, OK, EMPTY_LINE
};

typedef struct label{
  char  symbol[256];
  unsigned short location;
  struct label* next;
} label_t;

typedef struct instructions{
  unsigned short hexValue;
  struct instructions* next;
}intructions_t;

typedef struct oprand{
  char* name;
  char  value;
}oprand_t;


intructions_t* Instruction;
label_t*       Symbol_table;
oprand_t registers[8] = {
  {"r0",0},{"r1",1},{"r2",2},{"r3",3},
  {"r4",4},{"r5",5},{"r6",6},{"r7",7}};


FILE* infile = NULL;
FILE* outfile = NULL;

typedef enum opcodes_t {
  BR=0, ADD=1, LDB=2, STB=3, JSRR_JSR=4, AND =5, LDW=6,STW=7,
  RTI=8, XOR_NOT=9, RET_JMP=12, LSHF_RSHFL_RSHFA=13, LEA=14,
  TRAP=15,
  ORIG,FILL,HALT, END, NOP
};

#define NUM_INTRUCTION 31
char* OpCodes[NUM_INTRUCTION] = {"br","brn","brz","brp","brnz","brnzp",
  "brzp","brnp","add","ldb","stb",
  "jsr","jsrr","and","ldw",
  "stw","rti","xor","not",
  "ret","jmp","lshf","rshfl",
  "rshfa","lea","trap",".orig",
  ".fill","halt",".end","nop"};


int addIntruction(unsigned short hex) {
  intructions_t* current = NULL;

  if(!Instruction) {
    Instruction = (intructions_t*)malloc(sizeof(intructions_t));
    Instruction->hexValue = hex;
    Instruction->next = NULL;
    return DONE;
  }

  current = Instruction;
  while(current->next != NULL){
    current = current->next;
  }

  current->next = (intructions_t*)malloc(sizeof(intructions_t)); /*append new node*/
  current= current->next;
  current->hexValue=hex;
  current->next=NULL;

  return DONE;
}

void freeInstruction() {
  intructions_t* current;
  while (Instruction){
    current = Instruction;
    Instruction=Instruction->next;
    free (current);
  }
}

int isOpcode(char* opt){  
  int i;  /*look for instruction to compare with opt*/
  for(i = 0; i<NUM_INTRUCTION; i++) {
    if(strcmp(opt,OpCodes[i]) == 0)
      return 0;
  }
  return -1;
}

int toNum( char * pStr ){
  char * t_ptr;
  char * orig_pStr;
  int t_length,k;
  int lNum, lNeg = 0;
  long int lNumLong;

  orig_pStr = pStr;
  if( *pStr == '#' )				/* decimal */
  {
    pStr++;
    if( *pStr == '-' )				/* dec is negative */
    {
      lNeg = 1;
      pStr++;
    }
    t_ptr = pStr;
    t_length = strlen(t_ptr);
    for(k=0;k < t_length;k++)
    {
      if (!isdigit(*t_ptr))
      {
        printf("Error: invalid decimal operand, %s\n",orig_pStr);
        exit(4);
      }
      t_ptr++;
    }
    lNum = atoi(pStr);
    if (lNeg)
      lNum = -lNum;

    return lNum;
  }
  else if( *pStr == 'x' )	/* hex     */
  {
    pStr++;
    if( *pStr == '-' )	  /* hex is negative */
    {
      lNeg = 1;
      pStr++;
    }
    t_ptr = pStr;
    t_length = strlen(t_ptr);
    for(k=0;k < t_length;k++)
    {
      if (!isxdigit(*t_ptr))
      {
        printf("Error: invalid hex operand, %s\n",orig_pStr);
        exit(4);
      }
      t_ptr++;
    }
    lNumLong = strtol(pStr, NULL, 16);    /* convert hex string into integer */
    lNum = (lNumLong > INT_MAX)? INT_MAX : lNumLong;
    if( lNeg )
      lNum = -lNum;
    return lNum;
  }
  else
  {
    printf( "Error: invalid operand, %s\n", orig_pStr);
    exit(4);  /* This has been changed from error code 3 to error code 4, see clarification 12 */
  }
}

int insert_symbol_table(char* symbol, unsigned short location){
  label_t* current;
  int temp;

  if(Symbol_table==NULL){	             /*check if the table is empty*/
    Symbol_table = (label_t*)malloc(sizeof(label_t));
    strcpy(Symbol_table->symbol,symbol);
    Symbol_table->location= location;
    Symbol_table->next=NULL;
    return DONE;
  }
  current= Symbol_table;
  while(current->next != NULL){
    if(strcmp (current->symbol,symbol)==0){
      printf("Error: lable is used twice\n");
      return 4;                    /*lable is used twice*/
    }
    current= current->next;
  }

  current->next= (label_t*)malloc(sizeof(label_t)); /*append new node*/
  current= current->next;
  strcpy(current->symbol,symbol);
  current->location=location;
  current->next=NULL;
  return DONE;
}

void free_symbol_table(){
  label_t* current;
  
  while (Symbol_table){
    current = Symbol_table;
    Symbol_table=Symbol_table->next;
    free (current);
  }
}

unsigned short find_symbol(char*symbol){
  label_t* current;
  int i;
  if(Symbol_table==NULL){	             /*check if the table is empty*/
    exit(1);                           /*symbol not found*/
  }

  current = Symbol_table;
  while(current != NULL){
    i = strcmp(current->symbol,symbol);
    if(i == 0){
      return current->location;
    }
    current= current->next;
  }
  printf("Error: symbol not found\n");
  exit(1);                            /*symbol not found*/

}

int readAndParse( FILE * pInfile, char * pLine, char ** pLabel, 
                 char** pOpcode, char ** pArg1, char ** pArg2, 
                 char ** pArg3, char ** pArg4){
  char * lRet, * lPtr;
  int i;
  if( !fgets( pLine, MAX_LINE_LENGTH, pInfile ) )
    return( DONE );

  /* convert entire line to lowercase */
  for( i = 0; i < strlen( pLine ); i++ )
    pLine[i] = tolower( pLine[i] );

  *pLabel = *pOpcode = *pArg1 = *pArg2 = *pArg3 = *pArg4 = pLine + strlen(pLine);

  /* ignore the comments */
  lPtr = pLine;

  while( *lPtr != ';' && *lPtr != '\0' &&
    *lPtr != '\n' )
    lPtr++;

  *lPtr = '\0';
  if( !(lPtr = strtok( pLine, "\t\n ," ) ) )
    return( EMPTY_LINE );

  if( isOpcode( lPtr ) == -1 && lPtr[0] != '.' ) /* found a label */
  {
    *pLabel = lPtr;
    if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK );
  }

  *pOpcode = lPtr;

  if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK );

  *pArg1 = lPtr;

  if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK );

  *pArg2 = lPtr;
  if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK );

  *pArg3 = lPtr;

  if( !( lPtr = strtok( NULL, "\t\n ," ) ) ) return( OK );

  *pArg4 = lPtr;

  return( OK );
}

unsigned short getDrRegister(char* reg) {
  int index;
  for(index = 0; index < 8; index++) {
    if(strcmp(reg,registers[index].name) == 0 )
      return registers[index].value << 9;
  }
  return -1;
}

unsigned short getSr1Register(char* reg) {
  int index;
  for(index = 0; index < 8; index++) {
    if(strcmp(reg,registers[index].name) == 0 )
      return registers[index].value << 6;
  }
  return -1;
}

unsigned short getSr2Register(char* reg) {
  int index;
  for(index = 0; index < 8; index++) {
    if(strcmp(reg,registers[index].name) == 0 )
      return registers[index].value;
  }
  return -1;
}

int Parse(char* fileIn,char* fileOut) {
  char lLine[MAX_LINE_LENGTH + 1], *lLabel, *lOpcode, *lArg1, *lArg2, *lArg3, *lArg4;
  int err;
  int lRet;
  int OriginFound = 0;
  int OriginFound2 = 0;
  int EndFound = 0;
  unsigned short LC=0; 
  unsigned short hex_value,DR,SR1,SR2;
  short IMM;

  FILE * lInfile;

  lInfile = fopen( fileIn, "r" ); 	/* open the input file */
  if (!lInfile) {
    printf("Error: Cannot open file %s\n", fileIn);
    return 4;
  }

  do
  {
    lRet = readAndParse( lInfile, lLine, &lLabel,
      &lOpcode, &lArg1, &lArg2, 
      &lArg3, &lArg4 );
    if( lRet != DONE && lRet != EMPTY_LINE )
    {
/*parse 1*/
      if(!fileOut) { 
        if(strcmp(lOpcode,OpCodes[26]) == 0){   /*ORIG*/
          if(OriginFound) {
            printf("Error: Origin difined twice\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }
          LC = toNum(lArg1);
          /*we found origin*/
          OriginFound = 1;
          continue;
        }
        else if(strcmp(lOpcode,OpCodes[29]) == 0){ /*.end*/
          if(!OriginFound) {
            printf("Error: Origin not defined\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }
          fclose(lInfile); 	/* close the input file */
          return DONE;
        }
        else if(strcmp(lLabel,"") != 0){
          if((err = insert_symbol_table(lLabel,LC)) != DONE){
            fclose(lInfile); 	/* close the input file */
            return err;
          }
        }
        if(OriginFound && lOpcode) LC = LC+1;
      }  

/*parse 2*/
      else {
       
/*br*/
        if(strcmp(lOpcode,OpCodes[0]) == 0){                               
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile);     	/* close the input file */
            return 4;
          }

          IMM = (find_symbol(lArg1)-LC)-1;
          if(IMM > 511) exit(3);
          hex_value= 0x0000 | 0x0E00 | (IMM&0x1ff);
          addIntruction(hex_value);
        }

/*brn*/
        else if(strcmp(lOpcode,OpCodes[1]) == 0){                          
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          IMM = (find_symbol(lArg1)-LC)-1;
          if(IMM > 511) exit(3);
          hex_value= 0x0000 | 0x0800 | (IMM&0x1ff);
          addIntruction(hex_value);
        }


/*brz*/
        else if(strcmp(lOpcode,OpCodes[2]) == 0){                          
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          IMM = (find_symbol(lArg1)-LC)-1;
          if(IMM > 511) exit(3);
          hex_value= 0x0000 | 0x0400 | (IMM&0x1ff);
          addIntruction(hex_value);
        }

/*brp*/
        else if(strcmp(lOpcode,OpCodes[3]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          IMM = (find_symbol(lArg1)-LC)-1;
          if(IMM > 511) exit(3);
          hex_value= 0x0000 | 0x0200 | (IMM&0x1ff);
          addIntruction(hex_value);          
        }

/*brnz*/
        else if(strcmp(lOpcode,OpCodes[4]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          IMM = (find_symbol(lArg1)-LC)-1;
          if(IMM > 511) exit(3);
          hex_value= 0x0000 | 0x0C00 | (IMM&0x1ff);
          addIntruction(hex_value);          
        }

/*brnzp*/
        else if(strcmp(lOpcode,OpCodes[5]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          IMM = (find_symbol(lArg1)-LC)-1;
          if(IMM > 511) exit(3);
          hex_value= 0x0000 | 0x0E00 | (IMM&0x1ff);
          addIntruction(hex_value);      
        }

/*brzp*/
        else if(strcmp(lOpcode,OpCodes[6]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          IMM = (find_symbol(lArg1)-LC)-1;
          if(IMM > 511) exit(3);
          hex_value= 0x0000 | 0x0600 | (IMM&0x1ff);
          addIntruction(hex_value);     
        }

/*brnp*/
        else if(strcmp(lOpcode,OpCodes[7]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          IMM = (find_symbol(lArg1)-LC)-1;
          if(IMM > 511) exit(3);
          hex_value= 0x0000 | 0x0A00 | (IMM&0x1ff);
          addIntruction(hex_value);     
        }

/*add*/
        else if(strcmp(lOpcode,OpCodes[8]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          /*fetch operands*/
          if((DR  = getDrRegister(lArg1)) == 0xffff) exit(4);
          if((SR1 = getSr1Register(lArg2)) == 0xffff) exit(4);          
          
          if(*lArg3 == '#') {
            if((IMM = toNum(lArg3)) > 31 || (IMM < -32)) exit(3);
            hex_value = 0x1000 | DR | SR1 | (1<<5) | (IMM&0x1f);
          }
          else {
            if((SR2 = getSr2Register(lArg3)) == 0xffff) exit(4);    
            hex_value = 0x1000 | DR | SR1 | SR2;
          }
          
          addIntruction(hex_value);
        }

/*ldb*/
        else if(strcmp(lOpcode,OpCodes[9]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          /*fetch operands*/
          if((DR  = getDrRegister(lArg1)) == 0xffff) exit(4);
          if((SR1 = getSr1Register(lArg2)) == 0xffff) exit(4);          
          if((IMM = toNum(lArg3)) > 63) exit(3);
          hex_value = 0x2000 | DR | SR1 | IMM;
          addIntruction(hex_value);

        }

/*stb*/
        else if(strcmp(lOpcode,OpCodes[10]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }
          /*fetch operands*/
          if((DR  = getDrRegister(lArg1)) == 0xffff) exit(4);
          if((SR1 = getSr1Register(lArg2)) == 0xffff) exit(4);          
          if((IMM = toNum(lArg3)) > 63) exit(3);
          hex_value = 0x3000 | DR | SR1 | IMM;
          addIntruction(hex_value);

        }

/*jsr*/
        else if(strcmp(lOpcode,OpCodes[11]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          /*fetch operands*/
          IMM = (find_symbol(lArg1)-LC)-1;
          if(IMM > 2047) exit(3);

          hex_value = 0x4800 | (IMM&0x7ff);
          addIntruction(hex_value);

        }

/*jsrr*/
        else if(strcmp(lOpcode,OpCodes[12]) == 0){
         if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          if((SR1 = getSr1Register(lArg1)) == 0xffff) exit(4);          

          hex_value = 0x4000 | SR1 ;
          addIntruction(hex_value);  
        }

/*and*/
        else if(strcmp(lOpcode,OpCodes[13]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          /*fetch operands*/
          if((DR  = getDrRegister(lArg1))  == 0xffff) exit(4);
          if((SR1 = getSr1Register(lArg2)) == 0xffff) exit(4);          
          
          if(*lArg3 == '#') {
            if((IMM = toNum(lArg3)) > 31 || (IMM < -32)) exit(3);
            hex_value = 0x5000 | DR | SR1 | (1<<5) | (IMM&0x1f);
          }
          else {
            if((SR2 = getSr2Register(lArg3)) == 0xffff) exit(4);    
            hex_value = 0x5000 | DR | SR1 | SR2;
          }
          
          addIntruction(hex_value);
        }

/*ldw*/
        else if(strcmp(lOpcode,OpCodes[14]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }
          /*fetch operands*/
          if((DR  = getDrRegister(lArg1)) == 0xffff) exit(4);
          if((SR1 = getSr1Register(lArg2)) == 0xffff) exit(4);          
          if((IMM = toNum(lArg3)) > 63) exit(3);
          hex_value = 0x6000 | DR | SR1 | IMM;
          addIntruction(hex_value);
        }

/*stw*/
        else if(strcmp(lOpcode,OpCodes[15]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }
          /*fetch operands*/
          if((DR  = getDrRegister(lArg1)) == 0xffff) exit(4);
          if((SR1 = getSr1Register(lArg2)) == 0xffff) exit(4);          
          if((IMM = toNum(lArg3)) > 63) exit(3);
          hex_value = 0x7000 | DR | SR1 | IMM;
          addIntruction(hex_value);

        }

/*rti*/
        else if(strcmp(lOpcode,OpCodes[16]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          /*fetch operands*/        
          hex_value = 0x8000;
          addIntruction(hex_value);

        }

/*xor*/
        else if(strcmp(lOpcode,OpCodes[17]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          /*fetch operands*/
          if((DR  = getDrRegister(lArg1))  == 0xffff) exit(4);
          if((SR1 = getSr1Register(lArg2)) == 0xffff) exit(4);          
          
          if(*lArg3 == '#') {
            if((IMM = toNum(lArg3)) > 31 || (IMM < -32)) exit(3);
            hex_value = 0x9000 | DR | SR1 | (1<<5) | (IMM&0x1f);
          }
          else {
            if((SR2 = getSr2Register(lArg3)) == 0xffff) exit(4);    
            hex_value = 0x9000 | DR | SR1 | SR2;
          }
          
          addIntruction(hex_value);
        }

/*not*/
        else if(strcmp(lOpcode,OpCodes[18]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          /*fetch operands*/
          if((DR  = getDrRegister(lArg1)) == 0xffff) exit(4);
          if((SR1 = getSr1Register(lArg2)) == 0xffff) exit(4);          
          hex_value = 0x9000 | DR | SR1 | 0x003f;
          addIntruction(hex_value);

        }

/*ret*/
        else if(strcmp(lOpcode,OpCodes[19]) == 0){
         if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }       

          hex_value = 0xc1c0 ;
          addIntruction(hex_value);   
        }

/*jmp*/
        else if(strcmp(lOpcode,OpCodes[20]) == 0){
         if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          if((SR1 = getSr1Register(lArg1)) == 0xffff) exit(4);          

          hex_value = 0xc000 | SR1 ;
          addIntruction(hex_value);     
        
        }

/*lshf*/
        else if(strcmp(lOpcode,OpCodes[21]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          /*fetch operands*/
          if((DR  = getDrRegister(lArg1)) == 0xffff) exit(4);
          if((SR1 = getSr1Register(lArg2)) == 0xffff) exit(4); 
          if((IMM = toNum(lArg3)) > 15) exit(3);

          hex_value = 0xd000 | DR | SR1 | (IMM& 0xf);
          addIntruction(hex_value);

        }

/*rshfl*/
        else if(strcmp(lOpcode,OpCodes[22]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          /*fetch operands*/
          if((DR  = getDrRegister(lArg1)) == 0xffff) exit(4);
          if((SR1 = getSr1Register(lArg2)) == 0xffff) exit(4); 
          if((IMM = toNum(lArg3)) > 15) exit(3);

          hex_value = 0xd000 | DR | SR1 | 0x10|(IMM& 0xf);
          addIntruction(hex_value);

        }

/*rshfa*/
        else if(strcmp(lOpcode,OpCodes[23]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }

          /*fetch operands*/
          if((DR  = getDrRegister(lArg1)) == 0xffff) exit(4);
          if((SR1 = getSr1Register(lArg2)) == 0xffff) exit(4); 
          if((IMM = toNum(lArg3)) > 15) exit(3);

          hex_value = 0xd000 | DR | SR1 | 0x30|(IMM& 0xf);
          addIntruction(hex_value);

        }

/*lea*/
        else if(strcmp(lOpcode,OpCodes[24]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }
          /*fetch operands*/
          if((DR  = getDrRegister(lArg1)) == 0xffff) exit(4);
          IMM = (find_symbol(lArg2)-LC)-1;
          if(IMM > 511) exit(3);
          hex_value = 0xE000 | DR | (IMM&0x1ff);
          addIntruction(hex_value);
        }

/*trap*/
        else if(strcmp(lOpcode,OpCodes[25]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }
          if((IMM = toNum(lArg1)) > 127 || (IMM < -128)) exit(3);
          hex_value = 0xF000 | (IMM&0xff);
          addIntruction(hex_value);
        }

/*.orig*/
        else if(strcmp(lOpcode,OpCodes[26]) == 0){
          LC = toNum(lArg1);
          /*origin address cannot be odd*/
          if((LC%2) != 0 ) exit(3);
          addIntruction(LC);
          OriginFound2 = 1;
          continue;
        }

/*.fill*/
        else if(strcmp(lOpcode,OpCodes[27]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }
          hex_value = toNum(lArg1);
          addIntruction(hex_value);
        }

/*halt*/
        else if(strcmp(lOpcode,OpCodes[28]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }
          hex_value = 0xF025;
          addIntruction(hex_value);
        }

/*.end*/
        else if(strcmp(lOpcode,OpCodes[29]) == 0){
          if(!OriginFound2) {
            printf("Error: Instruction defined before origin\n");
            fclose(lInfile); 	/* close the input file */
            return 4;
          }
          fclose(lInfile); 	/* close the input file */
          return DONE;
        }

/*nop*/
        else if(strcmp(lOpcode,OpCodes[30]) == 0){
        }
        if(OriginFound2) LC = LC+1;
      }
    }
  } while( lRet != DONE );

  fclose(lInfile); 	/* close the input file */

  /*check for end of file reach on 1st pass */
  if((lRet == DONE) && !EndFound) {
    printf("Error: .END not defined\n");
    return 4;
  }
  return DONE;
}

int main(int argc, char* argv[]) {
  int   err;
  intructions_t* temp = NULL;
  char *prgName   = NULL;
  char *iFileName = NULL;
  char *oFileName = NULL;
  Symbol_table=NULL;
  prgName   = argv[0];
  iFileName = argv[1];
  oFileName = argv[2];

  printf("program name = '%s'\n", prgName);
  printf("input file name = '%s'\n", iFileName);
  printf("output file name = '%s'\n", oFileName);

  /* open the source file */
  outfile = fopen(argv[2], "w");

  if (!outfile) {
    printf("Error: Cannot open file %s\n", argv[2]);
    exit(4);
  }
  /*perform the first parse and fill the symbol table*/
  if (err = Parse (iFileName,0) != 0) {fclose(outfile); exit(err);}
  /*perform the second parse and build the instructions*/ 
  if (err = Parse (iFileName,oFileName) != 0) {fclose(outfile); exit(err);}

  /*fill the output file*/
  temp = Instruction;
  while(temp != NULL){
    fprintf( outfile, "0x%.4X\n", temp->hexValue );	/* where lInstr is declared as an int */
    temp = temp->next;
  }

  /*close output file*/
  fclose(outfile);

  free_symbol_table();
  freeInstruction();
}







